-- EmuLua script for graphing mathematical functions. ~bahamete
-- TODO: Fix messy code, add allowance for more complex functions,
-- such as parametric

-- OPTIONS -->
local X_MID = 120
local Y_MID = 117
local X_BOUND_LEFT = -30
local X_BOUND_RIGHT= 30
-- A lower value for X_INTERVAL means more lag, but more accuracy.
-- If you go too low, it will probably just freeze the emulator.
-- In fact, anything lower than 0.1 is probably too low for old CPUs.
local X_INTERVAL = 0.015

-- borrowed from a script by gocha. I like the colours
local color_table =
{
  "#ff9090",
  "#80ff80",
  "#a0a0ff",
  "#ffff80",
  "#ff80ff",
  "#80ffff"
}

-- Some example functions.
-- Functions must just return an x value
local functions = {
  function(x) return x end,
  function(x) return math.sin(x) end,
  function(x) return math.cos(x) end,
  function(x) return math.tan(x) end,
  function(x) return (((x+4) * (x+2) * (x+1) * (x-1) * (x-3)) / 20) + 2 end,
  function(x) return (x^2 + 1) * (x + 1) * (x-1)^2 end,
}

--< END OF OPTIONS

local function radToDeg(radians)
  local degrees = radians*(180 / math.pi)
  return degrees
end

local vals = {}

-- First, we fill vals table.
-- TODO optimize
for x = X_BOUND_LEFT, X_BOUND_RIGHT, X_INTERVAL do
  local y_vals = {}
  for _, f in pairs(functions) do
    local y = f(x)
    local y_def = Y_MID - y
    local x_def = X_MID + x

    if (y_def) > 0 and (y_def) < 255
   and (x_def) > 0 and (x_def) < 255 then
      y_vals[#y_vals + 1] = y
    end
  end
  if #y_vals > 0 then -- There's a chance all the functions
                      -- would go off screen. It's pointless to process.
    vals[#vals + 1] = y_vals
  end
end

gui.register(function()
  -- draw axis
  gui.transparency(2)
  gui.line(0, Y_MID, 255, Y_MID)
  gui.line(X_MID, 0, X_MID, 255)
  gui.transparency(0)

  for x = 1, #vals do
    local draw_x = X_BOUND_LEFT + (X_INTERVAL * x)

    for _y = 1, #vals[x] do
      local i = 1
      local draw_y = vals[x][_y] or 0
      gui.pixel(X_MID + draw_x * 10, Y_MID - draw_y * 10, color_table[_y] or "#FFFFFF")
    end
  end
end)
